package gaml.text;

import gaml.error.GamlException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * a line of yaml code with numerical identation
 * @author shnireck
 *
 */
public class YamlLine {
	final static Pattern pattern = Pattern.compile ("\\s*(?:!(\\S+)\\s*)?(?:&(\\S+)\\s*)?([^#]*)(?:#(.*))?");
	
	int ident = 0;
	
	String tag = "";
	String anchor = "";
	String value = "";
	
	public YamlLine () {}
	
	public YamlLine (String line, String identString, int shift) throws GamlException {
		if ((null == identString) || (0 == identString.length ())) throw new GamlException ("Identation string empty, configuration incorrect");
		
		Matcher matcher = pattern.matcher (parseIdentation (line, identString, shift));
		if (! matcher.find ()) throw new GamlException (String.format ("Incorrect YAML line format [%s]", line));
		
		if (null != matcher.group (1)) tag = matcher.group (1).trim ();
		if (null != matcher.group (2)) anchor = matcher.group (2).trim ();
		
		value = matcher.group (3).trim ();
	}
	
	/**
	 * @return line identation
	 */
	public int getIdent () { return ident; }
	public YamlLine setIdent (int ident) { this.ident = ident; return this; }
	
	/**
	 * @return tag specified in line
	 */
	public String getTag () { return tag; }
	public YamlLine setTag (String tag) { this.tag = tag; return this; }
	
	/**
	 * @return anchor specified in line
	 */
	public String getAnchor () { return anchor; }
	public YamlLine setAnchor (String anchor) { this.anchor = anchor; return this; } 
	
	/**
	 * @return line value
	 */
	public String getValue () { return value; }
	public YamlLine setValue (String value) { this.value = value; return this; }
	
	/**
	 * check if yaml line value is multiline
	 * @param lb line break
	 * @return true if line value is multyline
	 */
	public boolean isMultyline (String lb) { return value.trim ().contains (lb); }
	
	/**
	 * check if string is multyline
	 * @param value string to check
	 * @param lb line break
	 * @return true if value is multyline, false if not
	 */
	public static boolean isMultyline (String value, String lb) { return value.trim ().contains (lb); }
	
	/**
	 * check if line contains no information
	 * @return true if line is empty, false if it's not
	 */
	public boolean isEmpty () { return (tag.isEmpty () && anchor.isEmpty () && value.isEmpty ()); }
	
	/**
	 * get identation part from string
	 * @param line original yaml string
	 * @param identString single identation value 
	 * @return yaml line without identaion
	 */
	protected String parseIdentation (String line, String identString, int shift) throws GamlException {
		Matcher matcher = Pattern.compile (new StringBuilder (identString).append ("*(.*)").toString ()).matcher (line);
		matcher.find ();

		ident = (line.length () - matcher.group (1).length ()) / identString.length ();
		if (ident < shift) throw new GamlException (String.format ("Identation of line [%s] is less then it's parent identation (%d)", line, shift));
		ident -= shift;

		return matcher.group (1);
	}
}